﻿#include "stdafx.h"
#include "GameCoreScriptBinder.h"
#include "..\3rdLib\ASadd_on\scriptstring.h"
#include "..\3rdLib\ASadd_on\scriptstdstring.h"
#include "scriptwstring.h"

#include "DebugAssert.h"

_NAMESPACE_BEGIN

template<typename T>
static ostream* cout_value(const ostream& c,T v)
{
	cout<<v;
	return &cout;
}
static ostream* cout_str(const ostream& c,const string& v)
{
	wstring utf;
	CodeConvert::Instance()->UTF8_2Unicode(v.c_str(),utf);

	string str;
	CodeConvert::Instance()->Unicode2MultiByte(utf.c_str(),str);
	cout<<str;
	return &cout;
}

static ostream* cout_wstr(const ostream& c,const wstring& v)
{
	wprintf(L"%s", v.c_str());
	return &cout;
}

static string endl_value="\n";

template<typename T>
static T min_wrap(T t1,T t2)
{
	return min(t1,t2);
}
template<typename T>
static T max_wrap(T t1,T t2)
{
	return max(t1,t2);
}
template<typename T>
static T abs_wrap(T t)
{
	return abs(t);
}

Core_ScriptBinder::Core_ScriptBinder()
{
	AngelScriptBinder::CreateInstance();
	asIScriptEngine* engine=AngelScriptBinder::Instance()->GetEngine();

	int r;

	RegisterScriptString(engine);
	//RegisterStdString(engine);
	RegisterScriptWString(engine);
	//Bind_int3(engine);

	//AngelScriptBinder
	r=engine->RegisterObjectType("Binder",sizeof(AngelScriptBinder), asOBJ_REF | asOBJ_NOHANDLE );	assert( r >= 0 );
	r=engine->RegisterObjectMethod("Binder","int CompileScript(const string& in,const string& in)",asMETHOD(AngelScriptBinder,CompileScript), asCALL_THISCALL);	 assert( r >= 0 );
	r=engine->RegisterObjectMethod("Binder","void BindAllImportedFunctions(const string& in)",asMETHOD(AngelScriptBinder,BindAllImportedFunctions), asCALL_THISCALL);	 assert( r >= 0 );
	r=engine->RegisterGlobalProperty("Binder Binder_I",AngelScriptBinder::Instance() );	 assert( r >= 0 );

	//EventHandler
	r=engine->RegisterInterface("EventHandler");

	//endl
	r=engine->RegisterGlobalProperty("string endl",&endl_value);	 assert( r >= 0 );

	//cout
	r=engine->RegisterObjectType("ostream",0, asOBJ_REF );	assert( r >= 0 );
	DECLARE_EMPTY_ADD_RELEASE_REF(ostream)
	r=engine->RegisterGlobalProperty( "ostream cout",&wcout);	 assert( r >= 0 );
	r = engine->RegisterObjectMethod("ostream", "ostream@ opShl(float)",asFUNCTION(cout_value<float>), asCALL_CDECL_OBJFIRST);assert( r >= 0 );
	r = engine->RegisterObjectMethod("ostream", "ostream@ opShl(int)",asFUNCTION(cout_value<int>), asCALL_CDECL_OBJFIRST);assert( r >= 0 );
	r = engine->RegisterObjectMethod("ostream", "ostream@ opShl(uint)",asFUNCTION(cout_value<UINT>), asCALL_CDECL_OBJFIRST);assert( r >= 0 );
	r = engine->RegisterObjectMethod("ostream", "ostream@ opShl(double)",asFUNCTION(cout_value<double>), asCALL_CDECL_OBJFIRST);assert( r >= 0 );
	r = engine->RegisterObjectMethod("ostream", "ostream@ opShl(bool)",asFUNCTION(cout_value<bool>), asCALL_CDECL_OBJFIRST);assert( r >= 0 );
	r = engine->RegisterObjectMethod("ostream", "ostream@ opShl(const string&in)",asFUNCTION(cout_str), asCALL_CDECL_OBJFIRST);assert( r >= 0 );
	r = engine->RegisterObjectMethod("ostream", "ostream@ opShl(const wstring&in)",asFUNCTION(cout_wstr), asCALL_CDECL_OBJFIRST);assert( r >= 0 );

	//min
	r=engine->RegisterGlobalFunction("float min(float,float)",asFUNCTION(min_wrap<float>),asCALL_CDECL);assert( r >= 0 );
	r=engine->RegisterGlobalFunction("int min(int,int)",asFUNCTION(min_wrap<int>),asCALL_CDECL);	assert( r >= 0 );	
	//max
	r=engine->RegisterGlobalFunction("float max(float,float)",asFUNCTION(max_wrap<float>),asCALL_CDECL);assert( r >= 0 );
	r=engine->RegisterGlobalFunction("int max(int,int)",asFUNCTION(max_wrap<int>),asCALL_CDECL);		assert( r >= 0 );
	//abs
	r=engine->RegisterGlobalFunction("float abs(float)",asFUNCTION(abs_wrap<float>),asCALL_CDECL);assert( r >= 0 );
	r=engine->RegisterGlobalFunction("int abs(int)",asFUNCTION(abs_wrap<int>),asCALL_CDECL);	assert( r >= 0 );		

	///boost::any
	r = engine->RegisterObjectType("any", sizeof(any), asOBJ_VALUE | asOBJ_POD | asOBJ_APP_CLASS_C); assert( r >= 0 );
	DECLARE_CONSTRUCTOR(any)	
	r = engine->RegisterObjectBehaviour("any", asBEHAVE_DESTRUCT, "void f()", asFUNCTION(Destructor<any>), asCALL_CDECL_OBJLAST); assert( r >= 0 );
	r = engine->RegisterObjectBehaviour("any", asBEHAVE_CONSTRUCT, "void f(float)", asFUNCTION(cast_pod2any<float>), asCALL_CDECL_OBJLAST); assert( r >= 0 );
	r = engine->RegisterObjectBehaviour("any", asBEHAVE_IMPLICIT_VALUE_CAST, "float f()",asFUNCTION(cast_any2value<float>), asCALL_CDECL_OBJLAST);
	r = engine->RegisterObjectBehaviour("any", asBEHAVE_CONSTRUCT, "void f(int)", asFUNCTION(cast_pod2any<int>), asCALL_CDECL_OBJLAST); assert( r >= 0 );
	r = engine->RegisterObjectBehaviour("any", asBEHAVE_IMPLICIT_VALUE_CAST,"int f()",asFUNCTION(cast_any2value<int>), asCALL_CDECL_OBJLAST);
	//r = engine->RegisterObjectBehaviour("any", asBEHAVE_CONSTRUCT, "void f(const wstring& in)", asFUNCTION(cast_value2any<wstring>), asCALL_CDECL_OBJLAST); assert( r >= 0 );
	/*r = engine->RegisterGlobalFunction("wstring@ any2wstring(const any& in)", asFUNCTION(any2wstring), asCALL_CDECL); assert( r >= 0 );*/

	//Clock
	r=engine->RegisterObjectType("Clock",sizeof(Clock), asOBJ_REF  );	assert( r >= 0 );
	DECLARE_EMPTY_ADD_RELEASE_REF(Clock)
	r=engine->RegisterObjectMethod("Clock","void Start()", asMETHOD(Clock,Start), asCALL_THISCALL);	 assert( r >= 0 );
	r=engine->RegisterObjectMethod("Clock","double GetElapse()", asMETHOD(Clock,GetElapse), asCALL_THISCALL);	 assert( r >= 0 );
	r=engine->RegisterObjectMethod("Clock","double GetCurTime()", asMETHOD(Clock,GetCurTime), asCALL_THISCALL);	 assert( r >= 0 );
	r=engine->RegisterGlobalFunction("Clock@ New_Clock()",asFUNCTION(New_Type<Clock>), asCALL_CDECL);	 assert( r >= 0 );

	//ASEvent
	r=engine->RegisterObjectType("ASEvent",sizeof(ASEvent), asOBJ_REF  );	assert( r >= 0 );
	DECLARE_EMPTY_ADD_RELEASE_REF(ASEvent)
	TYPEMETHODS(ASEvent)
	r=engine->RegisterGlobalFunction("ASEvent@ New_ASEvent()",asFUNCTION(New_Type<ASEvent>), asCALL_CDECL);	 assert( r >= 0 );

	//Panel
	r=engine->RegisterObjectType("Panel",sizeof(Panel), asOBJ_REF  );	assert( r >= 0 );
	DECLARE_EMPTY_ADD_RELEASE_REF(Panel)
	TYPEMETHODS(Panel)

	//ParentPanel
	r=engine->RegisterObjectType("ParentPanel",sizeof(ParentPanel), asOBJ_REF );	assert( r >= 0 );
	DECLARE_EMPTY_ADD_RELEASE_REF(ParentPanel)
	DECLARE_DERIVE(ParentPanel,Panel)
	TYPEMETHODS(ParentPanel)

	///ASClockEvent
	//	r=engine->RegisterObjectType("ASClockEvent",sizeof(ASClockEvent), asOBJ_REF  );	assert( r >= 0 );
	//DECLARE_EMPTY_ADD_RELEASE_REF(ASClockEvent)
	//DECLARE_DERIVE(ASClockEvent,Panel)
	//TYPEMETHODS(ASClockEvent)
	//	r=engine->RegisterGlobalFunction("ASClockEvent@ New_ASClockEvent()",asFUNCTION(New_Type<ASClockEvent>), asCALL_CDECL);	 assert( r >= 0 );

	//GameCore
	r=engine->RegisterObjectType("GameCore",sizeof(GameCore), asOBJ_REF  );	assert( r >= 0 );
	DECLARE_EMPTY_ADD_RELEASE_REF(GameCore)
	DECLARE_DERIVE(GameCore,Panel)
	DECLARE_DERIVE(GameCore,ParentPanel)
	TYPEMETHODS(GameCore)
	r=engine->RegisterGlobalProperty( "GameCore GameCore_I",GameCore::Instance() );	 assert( r >= 0 );


	//BECode Open Type
	r=engine->RegisterEnum("OPEN_TYPE"); assert( r >= 0 );
	r=engine->RegisterEnumValue("OPEN_TYPE","OPEN_TYPE_READONLY",BECode::OPEN_TYPE_READONLY);
	r=engine->RegisterEnumValue("OPEN_TYPE","OPEN_TYPE_READWRITE",BECode::OPEN_TYPE_READWRITE);
	r=engine->RegisterEnumValue("OPEN_TYPE","OPEN_TYPE_NEW",BECode::OPEN_TYPE_NEW);

	//BECode
	r=engine->RegisterObjectType("BECode",sizeof(BECode),asOBJ_REF);	assert( r >= 0 );
	r = engine->RegisterObjectBehaviour("BECode", asBEHAVE_FACTORY,    "BECode @f()",                 asFUNCTION(BECodeDefaultFactory), asCALL_CDECL); assert( r >= 0 );
	r = engine->RegisterObjectBehaviour("BECode", asBEHAVE_ADDREF,     "void f()",                    asMETHOD(BECode,AddRef), asCALL_THISCALL); assert( r >= 0 );
	r = engine->RegisterObjectBehaviour("BECode", asBEHAVE_RELEASE,    "void f()",                    asMETHOD(BECode,Release), asCALL_THISCALL); assert( r >= 0 );

	r=engine->RegisterObjectMethod("BECode","bool AddNode(const string&in,const string&in)", asMETHODPR(BECode,AddNode<string>,(CONST_REF(string),CONST_REF(string)),bool), asCALL_THISCALL);	 assert( r >= 0 );
	r=engine->RegisterObjectMethod("BECode","bool AddNode(const string&in,const wstring&in)", asMETHODPR(BECode,AddNode<wstring>,(CONST_REF(string),CONST_REF(wstring)),bool), asCALL_THISCALL);	 assert( r >= 0 );
	r=engine->RegisterObjectMethod("BECode","bool ToParent()", asMETHOD(BECode,ToParent), asCALL_THISCALL);	 assert( r >= 0 );
	r=engine->RegisterObjectMethod("BECode","bool GetLastSon()", asMETHOD(BECode,GetLastSon), asCALL_THISCALL);	 assert( r >= 0 );

	r=engine->RegisterObjectMethod("BECode","bool Open(const wstring&in,OPEN_TYPE)", asMETHOD(BECode,Open), asCALL_THISCALL);	 assert( r >= 0 );
	r=engine->RegisterObjectMethod("BECode","void Save(const wstring&in)", asMETHOD(BECode,Save), asCALL_THISCALL);	 assert( r >= 0 );
	r=engine->RegisterObjectMethod("BECode","void Close()", asMETHOD(BECode,Close), asCALL_THISCALL);	 assert( r >= 0 );

	r=engine->RegisterObjectMethod("BECode","void FindNode(const string&in,bool)", asMETHOD(BECode,FindNode), asCALL_THISCALL);	 assert( r >= 0 );
	r=engine->RegisterObjectMethod("BECode","bool AddNode(const string&in,const uint&in)", asMETHODPR(BECode,AddNode<UINT>,(CONST_REF(string),CONST_REF(UINT)),bool), asCALL_THISCALL);	 assert( r >= 0 );
	r=engine->RegisterObjectMethod("BECode","bool AddNode(const string&in,const float&in)", asMETHODPR(BECode,AddNode<float>,(CONST_REF(string),CONST_REF(float)),bool), asCALL_THISCALL);	 assert( r >= 0 );
	r=engine->RegisterObjectMethod("BECode","void Read(wstring &out)", asMETHODPR(BECode,Read<wstring>,(wstring&),void), asCALL_THISCALL);	 assert( r >= 0 );
	r=engine->RegisterObjectMethod("BECode","void Read(float &out)", asMETHODPR(BECode,Read<float>,(float&),void), asCALL_THISCALL);	 assert( r >= 0 );
	r=engine->RegisterObjectMethod("BECode","void Read(uint32 &out)", asMETHODPR(BECode,Read<UINT>,(UINT&),void), asCALL_THISCALL);	 assert( r >= 0 );
	r=engine->RegisterObjectMethod("BECode","void Read(string &out)", asMETHODPR(BECode,Read<string>,(string&),void), asCALL_THISCALL);	 assert( r >= 0 );
	r=engine->RegisterObjectMethod("BECode","void Write(const string &in)", asMETHODPR(BECode,Write<string>,(const string&),void), asCALL_THISCALL);	 assert( r >= 0 );
}


_NAMESPACE_END